/*
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ru.vpitervip.app.client.ui;

import java.util.HashSet;
import java.util.List;
import java.util.logging.Logger;





import ru.vpitervip.app.client.activity.FlatsActivity;
import ru.vpitervip.app.client.util.MapUtil;
import ru.vpitervip.app.client.util.MyGeocoderCallback;
import ru.vpitervip.app.client.util.Settings;
import ru.vpitervip.client.managed.request.FlatProxy;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;


import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.i18n.shared.FirstStrongDirectionEstimator;
import com.google.gwt.maps.client.MapOptions;
import com.google.gwt.maps.client.MapTypeId;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.HasInfoWindowOptions;
import com.google.gwt.maps.client.base.HasLatLng;
import com.google.gwt.maps.client.base.InfoWindow;
import com.google.gwt.maps.client.base.InfoWindowOptions;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.event.Event;
import com.google.gwt.maps.client.event.EventCallback;
import com.google.gwt.maps.client.geocoder.Geocoder;
import com.google.gwt.maps.client.geocoder.GeocoderCallback;
import com.google.gwt.maps.client.geocoder.GeocoderRequest;
import com.google.gwt.maps.client.geocoder.HasGeocoder;
import com.google.gwt.maps.client.geocoder.HasGeocoderRequest;
import com.google.gwt.maps.client.geocoder.HasGeocoderResult;
import com.google.gwt.maps.client.overlay.HasMarker;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.impl.MarkerImpl;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.VerticalPanel;

import com.google.gwt.user.client.ui.Composite;



import com.google.gwt.user.client.ui.SimplePanel;

import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.cell.client.AbstractCell;


import com.google.gwt.safehtml.shared.SafeHtmlBuilder;


import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.HasRows;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.RangeChangeEvent;

import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;


/**
 * Sample implementation of {@link FlatsView}.
 */

public class FlatsViewImpl extends Composite implements FlatsView {
	
	
	private static final Logger log = Logger.getLogger(FlatsViewImpl.class.getName());

	interface Binder extends UiBinder<Widget, FlatsViewImpl> {
	}
	
	private static FlatsViewImpl instance;
	
	private static final Binder binder = GWT.create(Binder.class);
	
	private static final String FOTO_BASE_PATH="http://sutki-piter.ru/fotos/";
	
	
	private ProvidesKey<FlatProxy> keyProvider=new ProvidesKey<FlatProxy>(){

		@Override
		public Object getKey(FlatProxy item) {
			return item==null?null:item.getId();
		}



	};
	
	@UiField(provided=true) 
    CellList<FlatProxy> flatList = new CellList<FlatProxy>(new AbstractCell<FlatProxy>(){
		@Override
		public void render(Context context, FlatProxy value, SafeHtmlBuilder sb) {
			 if (value == null) {
			        return;
			      }
			 sb.appendHtmlConstant("<div  style='border: 1px solid   #e4a612; margin-top:3px;'>");
			 buildFlatBlock(value,sb,105,100,"");
			 sb.appendHtmlConstant("</div>");
		}
	},keyProvider);

	@UiField(provided=true)
	SimplePager flatListPager;
	@UiField SimplePanel rightPanel;
	@UiField SimplePanel leftPanel;
	@UiField AbsolutePanel flatListPanel;
	
	
	private FlatView flatView;
	
	private MapWidget mapWidget;
	
	private BookingView bookingView;
	
	private HashSet<HasMarker> mapMarkers;

	private Presenter listener;
	
	private AsyncDataProvider<FlatProxy> dataProvider;
	
	private IsWidget loadingWidget;

	public FlatsViewImpl() {
		
		AbsolutePanel absolutePanel=new AbsolutePanel();
		absolutePanel.setSize("100%", "100%");
		absolutePanel.add(new Image("images/loading.gif"), 140,200 ); 
		loadingWidget=absolutePanel;
		
		flatList.setLoadingIndicator(absolutePanel);
		
		
		AbsolutePanel emptyListWidget=new AbsolutePanel();
		emptyListWidget.setSize("100%", "100%");
		emptyListWidget.add(new HTML("Вариантов не найдено"), 120,200 ); 
		flatList.setEmptyListWidget(emptyListWidget);
		
		SimplePager.Resources pagerResources=GWT.create(SimplePager.Resources.class);
		flatListPager=new SimplePager(TextLocation.CENTER, pagerResources, false, 0, true){
			@Override
			protected void onRangeOrRowCountChanged() {
				super.onRangeOrRowCountChanged();
			}
			@Override
			protected String createText() {
				 // Default text is 1 based.
			    NumberFormat formatter = NumberFormat.getFormat("#,###");
			    HasRows display = getDisplay();
			    Range range = display.getVisibleRange();
			    int pageStart = range.getStart() + 1;
			    int pageSize = range.getLength();
			    int dataSize = display.getRowCount();
			    int endIndex = Math.min(dataSize, pageStart + pageSize - 1);
			    endIndex = Math.max(pageStart, endIndex);
			    boolean exact = display.isRowCountExact();
			    return formatter.format(pageStart) + "-" + formatter.format(endIndex)
			        + (exact ? " из " : " из ") + formatter.format(dataSize);
			}
		}; 
		flatListPager.setDisplay(flatList);
		
		
		final SingleSelectionModel<FlatProxy> selectionModel=new SingleSelectionModel<FlatProxy>();
		flatList.setSelectionModel(selectionModel);
	    selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
	      public void onSelectionChange(SelectionChangeEvent event) {
	    	  FlatProxy flatProxy=selectionModel.getSelectedObject();
	    	  if (selectionModel.isSelected(flatProxy)){
	    		  log.info("flat selected id:"+flatProxy.getId());
	    		  showFlat(flatProxy,false);
	    		  
	    	  }
	      }
	    });
	    
		
		initWidget(binder.createAndBindUi(this));
		
		
		rightPanel.setWidget(getMapWidget());
		
	}

	
	public static FlatsViewImpl instance(Presenter presenter){
		
		if (instance==null){
			instance=new FlatsViewImpl();
			instance.setPresenter(presenter);
		}else{
			instance.setPresenter(presenter);
			instance.updateList();
			instance.setLoading();
			
		}
		
		return instance;	
				
		
	}
	
	@Override
	public void showFlat(FlatProxy flatProxy, boolean standAlone){
		 getFlatView().setFlat(flatProxy,standAlone);
		 rightPanel.setWidget(getFlatView());
	}
	
	@SuppressWarnings("unchecked")
	@Override
    public void removeSelection(){
		SingleSelectionModel<FlatProxy> selectionModel=(SingleSelectionModel<FlatProxy>)flatList.getSelectionModel();
		FlatProxy flatProxy=selectionModel.getSelectedObject();
//		System.out.println("getSelected:"+flatProxy.getId());
		if (flatProxy!=null) selectionModel.setSelected(flatProxy, false);
    }


	@Override
	public void setFlatCount(int totalRows) {
		
		dataProvider.updateRowCount(totalRows, true);

	}
	
	public void setRangeData(int rangeStart,List<FlatProxy> flatProxies){
		
		dataProvider.updateRowData(rangeStart, flatProxies);
		updateMap(flatProxies);
	
	}
	
	private void  updateMap(List<FlatProxy> flatProxies){
		MapUtil.clearMapMapkers(mapMarkers);
		mapMarkers=new HashSet<HasMarker>();
		for (final FlatProxy flatProxy:flatProxies){	
			addMarker(flatProxy);	
		}		
	}
	
	
private void  addMarker(final FlatProxy flatProxy){
	
	    if (flatProxy==null) return; 
		
    	double lat=flatProxy.getLat();
		double lon=flatProxy.getLon();
		
		final String address=flatProxy.getAddress();
		
		if (lat>0&&lon>0){

			HasLatLng latLng=new LatLng(lat, lon);

			addMarker(latLng,flatProxy);


		}else{
			
			if (Settings.IS_DEBUGGING==1) return;
			
			if (address==null||address.length()<4) return;
			
			final HasGeocoderRequest gRequest =  new GeocoderRequest();
	        gRequest.setAddress("Санкт-Петербург "+address);
	        final HasGeocoder geocoder = new Geocoder();
	        geocoder.geocode(gRequest, new MyGeocoderCallback() {
	          
	          @Override
	          public void callback(List<HasGeocoderResult> responses, String status) {
//	        	  System.out.println("Answer received");
	            if (status.equals("OK")&&responses!=null&&responses.size()>0) {
	            	
	              final HasGeocoderResult gResult = responses.get(0);
	              final HasLatLng latLng = gResult.getGeometry().getLocation();
	              
	              addMarker(latLng,flatProxy);
	              
	            } else {
	              Window.alert("Geocoder failed with response : " + status);
	            }
	          }

			
	        });
		}
		
		
	}
    
    
    private void  addMarker(HasLatLng gLatLng,final FlatProxy flatProxy) {
    	// Add marker at the geocoder location.
    				final HasMarker marker = new Marker();
    				mapMarkers.add(marker);
    				marker.setPosition(gLatLng);
    				marker.setClickable(true);

    				final InfoWindow infoWindow=new InfoWindow();
    				
    				HasInfoWindowOptions options=new InfoWindowOptions() ;
    				options.setDisableAutoPan(true);
    				infoWindow.setOptions(options);
    				
    				SafeHtmlBuilder sb=new SafeHtmlBuilder();
    				buildFlatBlock(flatProxy,sb,90,85,"color:black");
    				String flatBlockHtml=sb.toSafeHtml().asString();
    				
    				infoWindow.setContent("<div style='color:black;padding-top:3px'>"+flatBlockHtml+"</div>");


    				//        Window.alert("setTitle");
    				//        marker.setTitle(address);


    				Event.addListener(marker, "click", new EventCallback(){
    					@Override
    					public void callback() {
    						flatList.getSelectionModel().setSelected(flatProxy, true);
    					}
    				});

    				Event.addListener(marker, "mouseover", new EventCallback(){
    					@Override
    					public void callback() {
    						infoWindow.open(mapWidget.getMap(), marker);
    					}
    				});

    				Event.addListener(marker, "mouseout", new EventCallback(){
    					@Override
    					public void callback() {
    						infoWindow.close();
    					}
    				});



    				marker.setMap(mapWidget.getMap());
    				// Pan to the geocoded location.
//    				mapWidget.getMap().panTo(latLng);
    				//   System.out.println("marker added");
		
	}
	
	
	private FlatView getFlatView(){
		
		if (flatView==null) {
			flatView=new FlatView();
			flatView.setSize("488px", "416px");
			flatView.setPresenter((FlatView.Presenter)listener);
		}
		
			return flatView;
	}
	
	
	private MapWidget getMapWidget(){
		
		if (mapWidget==null){
			
	
				final MapOptions options = new MapOptions();
			    // Zoom level. Required
			    options.setZoom(12);
			   
			    options.setCenter(new LatLng(59.946104,30.295516));
			    // Map type. Required.
			    options.setMapTypeId(new MapTypeId().getRoadmap());
			    
			    // Enable maps drag feature. Disabled by default.
			    options.setDraggable(true);
			    // Enable and add default navigation control. Disabled by default.
			    options.setNavigationControl(true);
			    // Enable and add map type control. Disabled by default.
			    options.setMapTypeControl(true);
			    mapWidget = new MapWidget(options);
			    mapWidget.setSize("465px", "610px");
			    
			    
                
			
		}
		
		return mapWidget;
	}
	
	
	

	@Override
	public void setPresenter(Presenter listener) {
		this.listener = listener;
		initDataPovider();
	}


	@Override
	public void startLoading() {
		flatListPager.startLoading();
		flatListPager.firstPage();
	}
     
	@Override
	public void goToFirstPage(){
		flatListPager.firstPage();
	}


	@Override
	public void updateList() {
		RangeChangeEvent.fire(flatList, new Range(0, 5));
		
	}



    private void initDataPovider(){
    	if (dataProvider==null){
    		dataProvider=new AsyncDataProvider<FlatProxy>() {

    			@Override
    			protected void onRangeChanged(HasData<FlatProxy> display) {
    				int start=0;
    				if (display.getVisibleRange()!=null) start=display.getVisibleRange().getStart();
    				if (listener!=null) listener.onFlatRangeChange(start);
    				log.info("dataProvider range changed");
    			}
    		};
    		dataProvider.addDataDisplay(flatList);
    	}
    }


	@Override
	public void showMap() {
		rightPanel.setWidget(getMapWidget());
		
	}


	@Override
	public void showFlatList() {
		leftPanel.setWidget(flatListPanel);
		
	}
	
	@Override
    public void showBookingView(int flatId,boolean standAlone){
    	leftPanel.setWidget(getBookingView(flatId,standAlone));
    }

    public BookingView getBookingView(int flatId,boolean standAlone){
    	if (bookingView==null){
    		bookingView=new BookingView();
    		bookingView.setPresenter((BookingView.Presenter)listener);
    	}
    	
    	bookingView.setStandAlone(standAlone);
    	bookingView.setFlatId(flatId);
    	
    	bookingView.setFormView();
    	
    	return bookingView;
    	
    }

    @Override
    public void setLoading(){
    	 
    	 if (loadingWidget!=null) leftPanel.setWidget(loadingWidget);
    	 
     }

    private String getFlatThumbnailHtml(FlatProxy value,int width,int height){
    	 String imageHtml="";
    	 //       if (value.getFacilities()!=null) System.out.println("facil:"+value.getFacilities().size());
    	 if (value.getFotos()!=null&&value.getFotos().size()>0){

    		 final String path=value.getFotos().get(0).getPath().substring(8);
//    		 SafeUri safeUri=new SafeUri() {
//				@Override
//				public String asString() {
//					return FOTO_BASE_PATH+path;
//				}
//			};  
//    		 ImageResourcePrototype resourcePrototype=new ImageResourcePrototype("картинка",safeUri ,3, 3, width, height, false, false);
//    		 imageHtml=AbstractImagePrototype.create(resourcePrototype).getHTML();
			
			 imageHtml= "<img src='"+FOTO_BASE_PATH+path+"' width='115px' height='105px' >";
			
			
    	 }
    	 return imageHtml;
     
     }
     
     
     private void buildFlatBlock(FlatProxy value,SafeHtmlBuilder sb,int width,int height,String style){
    	 String imageHtml=getFlatThumbnailHtml(value,width,height);
	      
	      sb.appendHtmlConstant("<table style='"+style+"'>");
	      sb.appendHtmlConstant("<tr><td rowspan='5'>");
	      sb.appendHtmlConstant(imageHtml);
	      sb.appendHtmlConstant("</td><td style='padding-left:4px'>"+"<b>Id: </b>");
	      if (value.getId()!=null) sb.appendEscaped(""+value.getId());
	      sb.appendHtmlConstant("</td></tr><tr><td style='padding-left:4px'>"+"<b>Адрес: </b>");
	      if (value.getAddress()!=null) sb.appendEscaped(value.getAddress());
	      sb.appendHtmlConstant("</td></tr><tr><td  style='padding-left:4px'>"+"<b>Общая площадь: </b>");
	      if (value.getArea()!=null) sb.appendEscaped(value.getArea()+" м²");
	      sb.appendHtmlConstant("</td></tr><tr><td  style='padding-left:4px'>"+"<b>Кол-во комнат: </b>");
	      if (value.getRoomNum()!=null) sb.appendEscaped(value.getRoomNum()+"");
	      sb.appendHtmlConstant("</td></tr><tr><td  style='padding-left:4px'>"+"<b>Цена: </b>");
	      if (value.getPrice()!=null) sb.appendEscaped(value.getPrice()+" руб./сут.");
	      sb.appendHtmlConstant("</td></tr></table>");
	      
    	 
     }


	@Override
	public BookingView getBookingView() {
		return bookingView;
	}
     
     

}
